﻿// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System.CommandLine;
using System.CommandLine.Binding;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;

namespace Microsoft.TemplateEngine.TemplateLocalizer.Commands
{
    /// <summary>
    /// Represents a <see cref="System.CommandLine.Command"/> together with its handler.
    /// </summary>
    internal abstract class ExecutableCommand<TModel> : Command where TModel : class
    {
        internal ExecutableCommand(string name, string? description = null, ILoggerFactory? loggerFactory = null)
            : base(name, description)
        {
            this.SetHandler((TModel model) => ExecuteAsync(model), GetModelBinder());
            LoggerFactory = loggerFactory;
            Logger = loggerFactory?.CreateLogger(GetType()) ?? NullLogger.Instance;
        }

        /// <summary>
        /// Gets a <see cref="ILoggerFactory"/> instance to be used for creating <see cref="ILogger"/> instances.
        /// </summary>
        protected ILoggerFactory? LoggerFactory { get; }

        /// <summary>
        /// Gets a <see cref="ILogger"/> instance to be used for logging the events generated by this command.
        /// </summary>
        protected ILogger Logger { get; }

        /// <summary>
        /// Executes the command with the given input.
        /// </summary>
        /// <param name="args">Arguments for the command.</param>
        protected abstract Task<int> ExecuteAsync(TModel args, CancellationToken cancellationToken = default);

        /// <summary>
        /// Gets the model binder for the command.
        /// </summary>
        /// <returns></returns>
        protected abstract BinderBase<TModel> GetModelBinder();
    }
}
